package middleware

import (
	"booking/common/handler"
	"booking/models"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt/v5"
	"github.com/spf13/cast"
	"github.com/spf13/viper"
)

type Admin struct {
	ID       int
	Username string
	Nickname string
	Mobile   string
}

func JWTAuth() gin.HandlerFunc {
	return func(c *gin.Context) {
		tokenString := c.GetHeader("Authorization")
		// 去除令牌前缀
		if strings.HasPrefix(tokenString, "Bearer ") {
			tokenString = tokenString[len("Bearer "):]
		} else {
			handler.Response(c, map[string]any{}, 4, "登录校验失败！")
			c.Abort()
			return
		}

		// 解析JWT令牌
		token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
			return []byte(viper.GetString("jwt.secret")), nil
		})

		// 验证令牌是否有效
		if err != nil || !token.Valid {
			handler.Response(c, map[string]any{}, 4, "登录验证失败！")
			c.Abort()
			return
		}

		// 将令牌声明转换为map类型
		claims, ok := token.Claims.(jwt.MapClaims)
		if !ok {
			handler.Response(c, map[string]any{}, 4, "登录失败！")
			c.Abort()
			return
		}

		// 检查是否过期
		expirationTime := time.Unix(int64(claims["expires"].(float64)), 0)
		if time.Now().After(expirationTime) {
			handler.Response(c, map[string]any{}, 4, "登录过期，请重新登录！")
			c.Abort()
			return
		}
		var adminInfo models.Admin
		models.Db.Model(models.Admin{}).
			Where(map[string]any{
				"id":     claims["id"],
				"status": models.StatusEnabled,
			}).
			First(&adminInfo)
		if adminInfo.Id == 0 {
			handler.Response(c, map[string]any{}, 4, "登录失败或已禁用！")
			c.Abort()
			return
		}

		//将用户信息存储到上下文中
		admin := Admin{
			ID:       cast.ToInt(claims["id"]),
			Username: claims["username"].(string),
			Nickname: claims["nickname"].(string),
			Mobile:   claims["mobile"].(string),
		}
		c.Set("admin", admin)
		c.Set("id", cast.ToInt(claims["id"]))
		c.Set("username", cast.ToString(claims["username"]))
		c.Set("mobile", cast.ToString(claims["mobile"]))
		c.Set("nickname", cast.ToString(claims["nickname"]))
		c.Next()
	}
}
